﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Inscriptionem.Areas.Inscriptionem.Models.Enums;
using Inscriptionem.Areas.Inscriptionem.Models.Requests;
using Inscriptionem.Areas.Inscriptionem.Models.Views;
using Inscriptionem.Authorization;
using Inscriptionem.Extensions;

namespace Inscriptionem.Areas.Inscriptionem.Controllers
{
    [InscriptionemAuthorize(MemberRole.Admin)]
    public class SectionController : Controller
    {
        private readonly ORM.DB DB;
        public SectionController()
        {
            DB = new ORM.DB();
        }

        public ActionResult Index()
        {
            return View("Index", new SectionCollectionViewModel());
        }

        [HttpPost]
        public ActionResult Add(SectionRequestModel model)
        {
            var result = new SectionViewModel();
            model.CopyTo(result);

            result.Error = ValidateSectionAddModel(result);

            if (result.Error == SectionError.None)
            {
                try
                {
                    // Save
                    if (result.IsDefault)
                    {
                        var existingSection = DB.Languages.First(l => l.ID == result.Language).Sections.FirstOrDefault(l => l.IsDefault);
                        if (existingSection != null)
                        {
                            existingSection.IsDefault = false;
                            existingSection.ModifiedDate = DateTime.Now;
                        }
                    }

                    var section = new ORM.Section()
                                      {
                                          Name = result.Name.Trim(),
                                          LocalizedName = result.LocalizedName.Trim(),
                                          IsDefault = result.IsDefault,
                                          Order = result.Order,
                                          Language = DB.Languages.First(l => l.ID == result.Language),
                                          CreatedDate = DateTime.Now,
                                          ModifiedDate = DateTime.Now
                                      };

                    DB.AddToSections(section);
                    DB.SaveChanges();
                }
                catch (Exception)
                {
                    result.Error = SectionError.Other;
                }
            }

            if (result.Error == SectionError.None)
            {
                return RedirectToAction("Index");
            }

            return View("Add", result);
        }

        [HttpPost]
        public ActionResult Edit(SectionRequestModel model)
        {
            var result = new SectionViewModel();
            model.CopyTo(result);

            if (result.ID > 0 && string.IsNullOrWhiteSpace(result.Name) && string.IsNullOrWhiteSpace(result.LocalizedName))
            {
                var section = DB.Sections.FirstOrDefault(s => s.ID == result.ID);
                if (section == null)
                {
                    // Section not found
                    return RedirectToAction("Index");
                }

                result.Order = section.Order;
                result.Name = section.Name;
                result.LocalizedName = section.LocalizedName;
                result.IsDefault = section.IsDefault;
                result.Language = section.Language.ID;

                return View("Edit", result);
            }

            // Validate
            result.Error = ValidateSectionEditModel(result);
            if (result.Error == SectionError.None)
            {
                // Save changes
                try
                {
                    var section = DB.Sections.FirstOrDefault(s => s.ID == result.ID);

                    if (section == null)
                    {
                        return RedirectToAction("Index");
                    }

                    section.Order = result.Order;
                    section.Name = result.Name.Trim();
                    section.LocalizedName = result.LocalizedName.Trim();
                    section.Language = DB.Languages.First(l => l.ID == result.Language);
                    section.ModifiedDate = DateTime.Now;

                    DB.SaveChanges();

                    return RedirectToAction("Index");
                }
                catch (Exception)
                {
                    result.Error = SectionError.Other;
                }
            }

            return View("Edit", result);
        }

        [HttpPost]
        public ActionResult Delete(int ID)
        {
            if (ID <= 0)
            {
                return RedirectToAction("Index");
            }

            var section = DB.Sections.FirstOrDefault(s => s.ID == ID);
            if (section == null)
            {
                return RedirectToAction("Index");
            }

            SectionError result = SectionError.None;

            try
            {
                if (section.Categories.Any() || section.Pages.Any())
                {
                    result = SectionError.SectionHasContent;
                }
                else
                {
                    if (section.IsDefault)
                    {
                        var defaultSection = section.Language.Sections.FirstOrDefault(s => s.ID != ID);
                        if (defaultSection != null)
                        {
                            defaultSection.IsDefault = true;
                            defaultSection.ModifiedDate = DateTime.Now;
                        }
                    }

                    DB.Sections.DeleteObject(section);
                    DB.SaveChanges();

                    return RedirectToAction("Index");
                }
            }
            catch (Exception)
            {
                result = SectionError.Other;
            }

            return View("Delete", result);
        }

        public ActionResult Order()
        {
            return View("Order", new SectionCollectionViewModel());
        }

        [HttpPost]
        public ActionResult Order(IList<SectionOrderRequestModel> sections)
        {
            var error = ValidateSectionOrderModel(sections);
            if (error == OrderError.None)
            {
                // Save
                foreach (var section in sections)
                {
                    var dbSection = DB.Sections.FirstOrDefault(s => s.ID == section.ID);
                    if (dbSection != null)
                    {
                        dbSection.Order = section.Order;
                        dbSection.ModifiedDate = DateTime.Now;
                    }
                }

                DB.SaveChanges();
            }

            return View("Order", new SectionCollectionViewModel() { Error = error });
        }

        #region Implementation
        private OrderError ValidateSectionOrderModel(IList<SectionOrderRequestModel> Sections)
        {
            if (Sections == null || Sections.Count == 0)
            {
                return OrderError.Other;
            }

            if (Sections.Any(s => s.Order <= 0))
            {
                return OrderError.OrderNotValid;
            }

            var lookup = Sections.ToLookup(s => s.Language);

            foreach (var group in lookup)
            {
                var list = new List<int>();

                foreach (var section in group)
                {
                    if (!list.Contains(section.Order))
                    {
                        list.Add(section.Order);
                    }
                    else
                    {
                        return OrderError.OrderDuplicate;
                    }
                }
            }

            return OrderError.None;
        }

        private SectionError ValidateSectionAddModel(SectionViewModel Model)
        {
            var editValidateResult = ValidateSectionEditModel(Model);
            if (editValidateResult != SectionError.None)
            {
                return editValidateResult;
            }

            var section = DB.Languages.First(l => l.ID == Model.Language).Sections.FirstOrDefault(s => s.Name.ToLower() == Model.Name.ToLower().Trim());
            if (section != null)
            {
                return SectionError.SectionAlreadyExists;
            }

            return SectionError.None;
        }

        private SectionError ValidateSectionEditModel(SectionViewModel Model)
        {
            if (string.IsNullOrWhiteSpace(Model.Name))
            {
                return SectionError.SectionEmpty;
            }

            if (string.IsNullOrWhiteSpace(Model.LocalizedName))
            {
                return SectionError.SectionLocalizationEmpty;
            }

            if (Model.Language <= 0 || DB.Languages.FirstOrDefault(l => l.ID == Model.Language) == null)
            {
                return SectionError.SectionLanguageEmpty;
            }

            if (Model.Order <= 0)
            {
                return SectionError.OrderNotValid;
            }

            var section = DB.Languages.First(l => l.ID == Model.Language).Sections.FirstOrDefault(s => s.Order == Model.Order);
            if (section != null && section.ID != Model.ID)
            {
                return SectionError.OrderAlreadyInUse;
            }

            return SectionError.None;
        }
        #endregion
    }
}
